package judesart.app.validation;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.Path.Node;

import judesart.app.shared.ValidationError;
import judesart.app.shared.ValidationException;

import org.springframework.stereotype.Service;

@Service
public class ValidatorImpl implements AppValidator
{
    private final Validator validator = Validation.buildDefaultValidatorFactory().getValidator();

    @Override
    public <T> void validate(T model, AppConstraintValidator<T>... validators)
            throws ValidationException
    {
        List<ValidationError> messages = new ArrayList<ValidationError>();
        Set<ConstraintViolation> errors = (Set) validator.validate(model);
        if (!errors.isEmpty())
        {
            for (ConstraintViolation error : errors)
            {
                ValidationError vError = new ValidationError();
                vError.setMessage(error.getMessage());
                StringBuffer buff = new StringBuffer();
                for (Node node : error.getPropertyPath())
                {
                    if (buff.length() > 0)
                    {
                        buff.append(".");
                    }
                    buff.append(node.getName());
                }
                vError.setFieldPath(buff.toString());
                messages.add(vError);
            }
        }
        if (validators != null)
        {
            for (AppConstraintValidator<T> validator : validators)
            {
                List<ValidationError> valMsgs = validator.validate(model);
                if (valMsgs != null)
                {
                    messages.addAll(valMsgs);
                }
            }
        }
        if (messages.size() > 0)
        {
            throw new ValidationException(messages);
        }
    }
}
